}
regs->eip += inst_len; /* advance %eip */
+ regs->eflags &= ~X86_EFLAGS_RF;
switch ( mmio_op->instr ) {
case INSTR_MOV:
/* IO read --> memory write */
if ( dir == IOREQ_READ ) errcode |= PFEC_write_access;
regs->eip -= inst_len; /* do not advance %eip */
+ regs->eflags |= X86_EFLAGS_RF; /* RF was set by original #PF */
hvm_inject_exception(TRAP_page_fault, errcode, addr);
return;
}
/* Failed on the page-spanning copy. Inject PF into
* the guest for the address where we failed */
regs->eip -= inst_len; /* do not advance %eip */
+ regs->eflags |= X86_EFLAGS_RF; /* RF was set by #PF */
/* Must set CR2 at the failing address */
addr += size - rv;
gdprintk(XENLOG_DEBUG, "Pagefault on non-io side of a "
static void inline __update_guest_eip(unsigned long inst_len)
{
- unsigned long current_eip, intr_shadow;
+ unsigned long x;
- current_eip = __vmread(GUEST_RIP);
- __vmwrite(GUEST_RIP, current_eip + inst_len);
+ x = __vmread(GUEST_RIP);
+ __vmwrite(GUEST_RIP, x + inst_len);
- intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
- if ( intr_shadow & (VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS) )
+ x = __vmread(GUEST_RFLAGS);
+ if ( x & X86_EFLAGS_RF )
+ __vmwrite(GUEST_RFLAGS, x & ~X86_EFLAGS_RF);
+
+ x = __vmread(GUEST_INTERRUPTIBILITY_INFO);
+ if ( x & (VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS) )
{
- intr_shadow &= ~(VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS);
- __vmwrite(GUEST_INTERRUPTIBILITY_INFO, intr_shadow);
+ x &= ~(VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS);
+ __vmwrite(GUEST_INTERRUPTIBILITY_INFO, x);
}
}
c->eip += __get_instruction_length(); /* Safe: MOV Cn, LMSW, CLTS */
c->esp = __vmread(GUEST_RSP);
- c->eflags = __vmread(GUEST_RFLAGS);
+ c->eflags = __vmread(GUEST_RFLAGS) & ~X86_EFLAGS_RF;
c->cr0 = v->arch.hvm_vmx.cpu_shadow_cr0;
c->cr3 = v->arch.hvm_vmx.cpu_cr3;
"Enabling CR0.PE at %%eip 0x%lx", eip);
if ( vmx_assist(v, VMX_ASSIST_RESTORE) )
{
- eip = __vmread(GUEST_RIP);
HVM_DBG_LOG(DBG_LEVEL_1,
"Restoring to %%eip 0x%lx", eip);
return 0; /* do not update eip! */